﻿using System;
using Project.Core.Model;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
using System.Text;
using Project.Core.Model.System;

namespace Project.Core.Token
{
    /// <summary>
    /// 令牌帮助类
    /// </summary>
    public class CoreToken
    {
        public static string secretKey { get; set; } = "Project's Secret Key";

        /// <summary>
        /// 构造函数
        /// </summary>
        public CoreToken() { }

        /// <summary>
        /// 颁发JWT字符串
        /// </summary>
        /// <param name="tokenModel"></param>
        /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作，则以当前时间点延长过期时间)</param>
        /// <param name="expiressAbsoulte">绝对过期时长</param>
        /// <returns></returns>
        public static string IssueJWT(User tokenModel, TimeSpan expiresSliding, TimeSpan expiresAbsoulte)
        {
            DateTime UTC = DateTime.Now;
            Claim[] claims = new Claim[]
               {
                   new Claim(JwtRegisteredClaimNames.Sub, tokenModel.Sub),  //Subject
                   new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // JWT ID  JWT的唯一标识
                   new Claim(JwtRegisteredClaimNames.Iat, UTC.ToString(), ClaimValueTypes.Integer64) // Issued At JWT颁发时间，采用unix时间，用于验证过期
               };

            JwtSecurityToken jwt = new JwtSecurityToken(
                issuer: "Project",  // jwt签发者,非必须
                audience: "wr",
                // audience: tokenModel.UserName, // jwt的接收方， 非必须
                claims: claims,  // 声明集合
                expires: UTC.AddHours(12), // 指定token的生命周期，unix时间戳格式，非必须
                signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey)), SecurityAlgorithms.HmacSha256));

            var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); // 生成最后的jwt字符串

            // 将JWT字符串和tokenModel作为key和value存入缓存
            CoreMemoryCache.AddMemoryCache(encodedJwt, tokenModel, expiresSliding, expiresAbsoulte);

            return encodedJwt;
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="jwtStr"></param>
        /// <returns></returns>
        public static User SerializeJWT(string jwtStr)
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
            object role = new object(); ;
            try
            {
                jwtToken.Payload.TryGetValue("Role", out role);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            var tm = new User
            {
                UserName = jwtToken.Id
            };
            return tm;
        }
    }
}
